﻿using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using Foundation.ExtensionMethods;

namespace Poet.Views
{
    /// <summary>
    /// Interaction logic for BorderBoxView.xaml
    /// </summary>
    public partial class PaletteBoxView
    {
        public PaletteBoxView()
        {
            InitializeComponent();
        }

        public bool BrushMode { get; set; }

        public static readonly DependencyProperty PenProperty =
            DependencyProperty.Register("Pen", typeof (Pen), typeof (PaletteBoxView),
                                         new FrameworkPropertyMetadata(
                                            default(Pen),
                                            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                                                             (o, args) =>
                                                                 {
                                                                     var @this = (PaletteBoxView) o;
                                                                     var newPen = args.NewValue as Pen;
                                                                     if (newPen == null)
                                                                     {
                                                                         @this.SampleBrush = null;
                                                                         return;
                                                                     }

                                                                     if (newPen.Brush is SolidColorBrush &&
                                                                         !Equals(@this.Brush, newPen.Brush))
                                                                         @this.SampleBrush =
                                                                             new SolidColorBrush(
                                                                                 ((SolidColorBrush) newPen.Brush).Color);
                                                                     if (!Equals(@this.Thickness, newPen.Thickness))
                                                                         @this.Thickness = newPen.Thickness;
                                                                     
                                                                     if (!newPen.IsFrozen)
                                                                         newPen.Freeze();
                                                                 }));

        public Pen Pen
        {
            get { return (Pen) GetValue(PenProperty); }
            set { SetValue(PenProperty, value); }
        }

        public static readonly DependencyProperty ThicknessProperty =
            DependencyProperty.Register("Thickness", typeof (double), typeof (PaletteBoxView),
                                         new FrameworkPropertyMetadata(
                                            1.0d,
                                            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                                                             (o, args) =>
                                                                 {
                                                                     var @this = (PaletteBoxView) o;
                                                                     if (@this.Brush == null) return;
                                                                     var newThickness = (double) args.NewValue;
                                                                     if (@this.Pen.IsFrozen)
                                                                     {
                                                                         @this.Pen =
                                                                             @this.Brush == null
                                                                                 ? null
                                                                                 : new Pen(@this.Brush, newThickness);
                                                                     }
                                                                     else @this.Brush.Opacity = newThickness;
                                                                 }));

        public double Thickness
        {
            get { return (double) GetValue(ThicknessProperty); }
            set { SetValue(ThicknessProperty, value); }
        }

        public static readonly DependencyProperty CornerRadiusProperty =
            DependencyProperty.Register("CornerRadius", typeof (double), typeof (PaletteBoxView),
                                        new FrameworkPropertyMetadata(
                                            3.0d,
                                            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault));

        public double CornerRadius
        {
            get { return (double) GetValue(CornerRadiusProperty); }
            set { SetValue(CornerRadiusProperty, value); }
        }

        public static readonly DependencyProperty BrushProperty =
            DependencyProperty.Register("Brush", typeof (SolidColorBrush), typeof (PaletteBoxView),
                                        new FrameworkPropertyMetadata(
                                            default(SolidColorBrush),
                                            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                                            (o, args) =>
                                                {
                                                    var @this = (PaletteBoxView) o;
                                                    var newBrush = args.NewValue as SolidColorBrush;
                                                    if (newBrush == null)
                                                    {
                                                        @this.SampleBrush = null;
                                                        @this.Pen = null;
                                                        return;
                                                    }

                                                    if (@this.SampleBrush == null ||
                                                        !Equals(newBrush.Color, @this.SampleBrush.Color))
                                                        @this.SampleBrush = new SolidColorBrush(newBrush.Color);
                                                    if (!Equals(newBrush.Opacity, @this.BrushOpacity))
                                                        @this.BrushOpacity = newBrush.Opacity;

                                                    if (!newBrush.IsFrozen)
                                                        newBrush.Freeze();

                                                    if (!@this.BrushMode)
                                                        @this.Pen = new Pen(@this.Brush, @this.Thickness);
                                                }));

        public SolidColorBrush Brush
        {
            get { return (SolidColorBrush) GetValue(BrushProperty); }
            set { SetValue(BrushProperty, value); }
        }

        private static readonly DependencyProperty BrushOpacityProperty =
            DependencyProperty.Register("BrushOpacity", typeof (double), typeof (PaletteBoxView),
                                        new PropertyMetadata(
                                            0.5d,
                                            (o, args) =>
                                                {
                                                    var @this = (PaletteBoxView) o;
                                                    if (@this.Brush == null) return;
                                                    var newOpacity = (double) args.NewValue;
                                                    if (@this.Brush.IsFrozen)
                                                    {
                                                        @this.Brush =
                                                            @this.SampleBrush == null
                                                                ? null
                                                                : new SolidColorBrush(@this.Brush.Color)
                                                                    {
                                                                        Color = @this.SampleBrush.Color,
                                                                        Opacity = newOpacity
                                                                    };
                                                    }
                                                    else @this.Brush.Opacity = newOpacity;
                                                }));

        private double BrushOpacity
        {
            get { return (double) GetValue(BrushOpacityProperty); }
            set { SetValue(BrushOpacityProperty, value); }
        }

        private static readonly DependencyProperty SampleBrushProperty =
            DependencyProperty.Register("SampleBrush", typeof (SolidColorBrush), typeof (PaletteBoxView),
                                        new FrameworkPropertyMetadata(
                                            default(SolidColorBrush),
                                            FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
                                            (o, args) =>
                                                {
                                                    var @this = (PaletteBoxView) o;
                                                    var newSampleBrush = args.NewValue as SolidColorBrush;
                                                    @this.Brush =
                                                        newSampleBrush == null
                                                            ? null
                                                            : new SolidColorBrush(newSampleBrush.Color)
                                                                {
                                                                    Opacity = @this.BrushOpacity
                                                                };
                                                }));

        private SolidColorBrush SampleBrush
        {
            get { return (SolidColorBrush) GetValue(SampleBrushProperty); }
            set { SetValue(SampleBrushProperty, value); }
        }

        public static IList<PaletteInfo> DefaultPalette = GetDefaultPalette();

        public class PaletteInfo
        {
            public Pen Pen { get; set; }

            public Brush Fill { get; set; }

            public string Name { get; set; }

            public override string ToString()
            {
                return Name;
            }
        }

        private static IList<PaletteInfo> GetDefaultPalette()
        {
            return
                typeof(Brushes).GetProperties().Select(
                    p =>
                    new PaletteInfo
                    {
                        Pen = new Pen { Brush = (Brush)p.GetValue(null) },
                        Fill = ((Brush)p.GetValue(null)).Clone(),
                        Name = p.Name
                    }).ToList();
        }

        private void Handle(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
        }
    }
}